home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir24
/
psi110g.zip
/
AX25SUBR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-17
|
7KB
|
282 lines
/* low level AX25 routines:
* callsign conversion
* control block management
*
* Copyright 1991 Phil Karn, KA9Q
*/
/* Mods by G1EMM */
#include "global.h"
#ifdef AX25
#include "mbuf.h"
#include "timer.h"
#include "ax25.h"
#include "lapb.h"
#include <ctype.h>
struct ax25_cb *Ax25_cb;
/* Default AX.25 parameters */
int32 T3init = 0; /* No keep-alive polling */
int32 T4init = 300; /* 5 Minutes of no I frame tx or rx => redundant link */
int16 Maxframe = 1; /* Stop and wait */
int16 N2 = 10; /* 10 retries */
int16 Axwindow = 2048; /* 2K incoming text before RNR'ing */
int16 Paclen = 256; /* 256-byte I fields */
int16 Pthresh = 128; /* Send polls for packets larger than this */
int32 Axirtt = 5000; /* Initial round trip estimate, ms */
int16 Axversion = V2; /* Protocol version */
int32 Blimit = 30; /* Retransmission backoff limit */
/* Look up entry in connection table
* Check BOTH the source AND destination address
* Added 11/15/91, WG7J/PA3DIS
*/
struct ax25_cb *
find_ax25(local,remote,iface)
char *local;
char *remote;
struct iface *iface;
{
register struct ax25_cb *axp;
struct ax25_cb *axlast = NULLAX25;
/* Search list */
for(axp = Ax25_cb; axp != NULLAX25;axlast=axp,axp = axp->next){
if(addreq(axp->remote,remote) && addreq(axp->local,local) \
&& axp->iface == iface) {
if(axlast != NULLAX25){
/* Move entry to top of list to speed
* future searches
*/
axlast->next = axp->next;
axp->next = Ax25_cb;
Ax25_cb = axp;
}
return axp;
}
}
return NULLAX25;
}
/* Remove address entry from connection table */
void
del_ax25(conn)
struct ax25_cb *conn;
{
register struct ax25_cb *axp;
struct ax25_cb *axlast = NULLAX25;
for(axp = Ax25_cb; axp != NULLAX25; axlast=axp,axp = axp->next){
if(axp == conn)
break;
}
if(axp == NULLAX25)
return; /* Not found */
/* Remove from list */
if(axlast != NULLAX25)
axlast->next = axp->next;
else
Ax25_cb = axp->next;
/* Timers should already be stopped, but just in case... */
stop_timer(&axp->t1);
stop_timer(&axp->t3);
stop_timer(&axp->t4);
axp->r_upcall = NULLVFP;
axp->s_upcall = NULLVFP;
axp->t_upcall = NULLVFP;
/* Free allocated resources */
free_q(&axp->txq);
free_q(&axp->rxasm);
free_q(&axp->rxq);
free((char *)axp);
}
/* Create an ax25 control block. Allocate a new structure, if necessary,
* and fill it with all the defaults.
*/
/* This takes BOTH source and destination address.
* 11/15/91, WG7J/PA3DIS
*/
/* Modified to take the Irtt from the interface - 11/22/93 - WG7J */
struct ax25_cb *
cr_ax25(local,remote,iface)
char *local;
char *remote;
struct iface *iface;
{
struct ax25_cb *axp;
struct ifax25 *ifax;
if((remote == NULLCHAR) || (local == NULLCHAR))
return NULLAX25;
/* Create an entry
* and insert it at the head of the chain
*/
axp = (struct ax25_cb *)callocw(1,sizeof(struct ax25_cb));
axp->next = Ax25_cb;
Ax25_cb = axp;
/*fill in 'defaults'*/
memcpy(axp->local,local,AXALEN);
memcpy(axp->remote,remote,AXALEN);
axp->user = -1;
axp->state = LAPB_DISCONNECTED;
if(iface && (ifax=iface ->ax25) != NULL) {
axp->maxframe = ifax->maxframe;
axp->window = ifax->window;
axp->iface = iface;
axp->paclen = ifax->paclen;
axp->proto = ifax->version; /* Default, can be changed by other end */
axp->pthresh = ifax->pthresh;
axp->n2 = ifax->n2;
axp->srt = ifax->irtt;
set_timer(&axp->t1,2*axp->srt);
set_timer(&axp->t3,ifax->t3);
set_timer(&axp->t4,ifax->t4 * 1000L);
}
axp->t1.func = recover;
axp->t1.arg = axp;
axp->t3.func = pollthem;
axp->t3.arg = axp;
axp->t4.func = redundant;
axp->t4.arg = axp;
/* Always to a receive and state upcall as default */
/* Also bung in a default transmit upcall - in case */
axp->r_upcall = s_arcall;
axp->s_upcall = s_ascall;
axp->t_upcall = s_atcall;
return axp;
}
/*
* setcall - convert callsign plus substation ID of the form
* "KA9Q-0" to AX.25 (shifted) address format
* Address extension bit is left clear
* Return -1 on error, 0 if OK
*/
int
setcall(out,call)
char *out;
char *call;
{
int csize;
unsigned ssid;
register int i;
register char *dp;
char c;
if(out == NULLCHAR || call == NULLCHAR || *call == '\0')
return -1;
/* Find dash, if any, separating callsign from ssid
* Then compute length of callsign field and make sure
* it isn't excessive
*/
dp = strchr(call,'-');
if(dp == NULLCHAR)
csize = strlen(call);
else
csize = (int)(dp - call);
if(csize > ALEN)
return -1;
/* Now find and convert ssid, if any */
if(dp != NULLCHAR){
dp++; /* skip dash */
ssid = atoi(dp);
if(ssid > 15)
return -1;
} else
ssid = 0;
/* Copy upper-case callsign, left shifted one bit */
for(i=0;i<csize;i++){
c = *call++;
if(islower(c))
c = toupper(c);
*out++ = c << 1;
}
/* Pad with shifted spaces if necessary */
for(;i<ALEN;i++)
*out++ = ' ' << 1;
/* Insert substation ID field and set reserved bits */
*out = 0x60 | (ssid << 1);
return 0;
}
int
addreq(a,b)
register char *a,*b;
{
if(memcmp(a,b,ALEN) != 0 || ((a[ALEN] ^ b[ALEN]) & SSID) != 0)
return 0;
else
return 1;
}
/* Convert encoded AX.25 address to printable string */
char *
pax25(e,addr)
char *e;
char *addr;
{
register int i;
char c;
char *cp;
cp = e;
for(i=ALEN;i != 0;i--){
c = (*addr++ >> 1) & 0x7f;
if(c != ' ')
*cp++ = c;
}
if ((*addr & SSID) != 0)
sprintf(cp,"-%d",(*addr >> 1) & 0xf); /* ssid */
else
*cp = '\0';
return e;
}
/* Figure out the frame type from the control field
* This is done by masking out any sequence numbers and the
* poll/final bit after determining the general class (I/S/U) of the frame
*/
int16
ftype(control)
register int control;
{
if((control & 1) == 0) /* An I-frame is an I-frame... */
return I;
if(control & 2) /* U-frames use all except P/F bit for type */
return (int16)(uchar(control) & ~PF);
else /* S-frames use low order 4 bits for type */
return (int16)(uchar(control) & 0xf);
}
#ifndef LINUX
void
lapb_garbage(red)
int red;
{
register struct ax25_cb *axp;
for(axp=Ax25_cb;axp != NULLAX25;axp = axp->next){
mbuf_crunch(&axp->rxq);
mbuf_crunch(&axp->rxasm);
}
}
#endif /* LINUX */
#endif /* AX25 */